package net.protocol.diameter.avp;

import java.nio.ByteBuffer;
import java.nio.charset.Charset;

/**
 * <pre>
 *   UTF8String
 *      The UTF8String format is derived from the OctetString AVP Base
 *      DiameterFormat.  This is a human readable string represented using the
 *      ISO/IEC IS 10646-1 character set, encoded as an OctetString using
 *      the UTF-8 [UFT8] transformation format described in RFC 2279.
 *
 *      Since additional code points are added by amendments to the 10646
 *      standard from time to time, implementations MUST be prepared to
 *      encounter any code point from 0x00000001 to 0x7fffffff.  Byte
 *      sequences that do not correspond to the valid encoding of a code
 *      point into UTF-8 charset or are outside this range are prohibited.
 *
 *      The use of control codes SHOULD be avoided.  When it is necessary
 *      to represent a new line, the control code sequence CR LF SHOULD be
 *      used.
 *
 *      The use of leading or trailing white space SHOULD be avoided.
 *
 *      For code points not directly supported by user interface hardware
 *      or software, an alternative means of entry and display, such as
 *      hexadecimal, MAY be provided.
 *
 *      For information encoded in 7-bit US-ASCII, the UTF-8 charset is
 *      identical to the US-ASCII charset.
 *
 *      UTF-8 may require multiple bytes to represent a single character /
 *      code point; thus the length of an UTF8String in octets may be
 *      different from the number of characters encoded.
 *
 *      Note that the AVP Length field of an UTF8String is measured in
 *      octets, not characters.
 * </pre>
 *
 * @author jinhongw@gmail.com
 */
public class UTF8String extends OctetString {
    protected final static Charset UTF8_CHARSET = Charset.forName("UTF-8");

    /**
     * @param code AVP Code
     * @param data AVP Data
     */
    public UTF8String(int code, String data) {
        this(code, data.getBytes(UTF8_CHARSET));
    }

    /**
     * @param code AVP Code
     * @param data AVP Data
     */
    protected UTF8String(int code, byte[] data) {
        this(code, DEFAULT_VENDOR_ID, data);
    }

    /**
     * @param code     AVP Code
     * @param vendorId Vendor-ID
     * @param data     AVP Data
     */
    public UTF8String(int code, int vendorId, String data) {
        this(code, vendorId, data.getBytes(UTF8_CHARSET));
    }

    /**
     * @param code     AVP Code
     * @param vendorId Vendor-ID
     * @param data     AVP Data
     */
    protected UTF8String(int code, int vendorId, byte[] data) {
        super(code, vendorId, data);
    }

    /**
     * Creates a new <code>UTF8String</code> with the given DiameterAVPHeader and source ByteBuffer
     *
     * @param header Diameter AVP Header
     * @param src The buffer from which bytes are to be retrieved
     */
    UTF8String(DiameterAVPHeader header, ByteBuffer src) {
        super(header, src);
    }

    @Override
    public String getData() {
        return new String(getDataBytes(), UTF8_CHARSET);
    }

    @Override
    public final DataFormat getType() {
        return DataFormat.UTF8String;
    }

    @Override
    public String getName() {
        return DataFormat.UTF8String.name();
    }

    @Override
    protected void detail(StringBuilder buf) {
        buf.append(new String(getDataBytes(), UTF8_CHARSET));
    }
}
